"""
辅助函数模块
"""
import re
import uuid
from datetime import datetime
from typing import List, Dict, Any, Optional
from app.utils.logger import logger


def generate_uuid() -> str:
    """生成UUID"""
    return str(uuid.uuid4())


def validate_chinese_text_length(text: str, max_length: int) -> bool:
    """验证中文文本长度"""
    return len(text) <= max_length


def clean_text(text: str) -> str:
    """清理文本内容"""
    # 移除多余的空白字符
    text = re.sub(r'\s+', ' ', text)
    # 移除首尾空白
    text = text.strip()
    return text


def split_content_into_paragraphs(content: str, min_paragraph_length: int = 50) -> List[str]:
    """将内容分割成段落"""
    # 按双换行符分割（与微信富文本格式一致）
    paragraphs = content.split('\n\n')
    
    # 清理和过滤段落
    cleaned_paragraphs = []
    
    for paragraph in paragraphs:
        paragraph = paragraph.strip()
        if not paragraph:
            continue
        
        # 如果段落长度足够，则作为一个独立段落
        if len(paragraph) >= min_paragraph_length:
            cleaned_paragraphs.append(paragraph)
        else:
            # 如果段落太短，仍然保留为独立段落（不合并）
            cleaned_paragraphs.append(paragraph)
    
    return cleaned_paragraphs


def calculate_image_positions(content: str, num_images: int) -> List[int]:
    """计算图片在内容中的插入位置"""
    paragraphs = split_content_into_paragraphs(content)
    total_paragraphs = len(paragraphs)
    
    if num_images <= 0 or total_paragraphs <= 0:
        return []
    
    if num_images >= total_paragraphs:
        # 每段一张图片
        return list(range(total_paragraphs))
    
    # 平均分布图片
    positions = []
    interval = total_paragraphs / num_images
    
    for i in range(num_images):
        position = int(i * interval)
        if position < total_paragraphs:
            positions.append(position)
    
    return positions


def insert_images_into_content(content: str, media_ids: List[str]) -> str:
    """将图片插入到内容中（使用微信正确的图片格式）"""
    if not media_ids:
        return content
    
    paragraphs = split_content_into_paragraphs(content)
    positions = calculate_image_positions(content, len(media_ids))
    
    # 从后往前插入，避免位置偏移
    for i in reversed(range(len(positions))):
        if i < len(media_ids) and positions[i] < len(paragraphs):
            media_id = media_ids[i]
            # 使用微信富文本编辑器的完整格式
            image_tag = f'<img class="rich_pages wxw-img" style="width:100%;height:auto;margin:10px 0" contenteditable="false" src="{media_id}" data-src="{media_id}" data-s="300,640" data-type="png" data-croporisrc="{media_id}" data-cropselx2="51" data-cropsely2="27" data-imgfileid="{media_id}" data-ratio="1" data-w="1024" data-imgqrcoded="1">'
            
            # 在段落后插入图片
            if positions[i] + 1 < len(paragraphs):
                paragraphs.insert(positions[i] + 1, image_tag)
            else:
                paragraphs.append(image_tag)
    
    return '\n\n'.join(paragraphs)


def insert_images_into_wechat_content(content: str, image_data: List[dict]) -> str:
    """
    专门用于微信草稿的图片插入函数
    
    支持使用微信CDN URL和完整的data属性，匹配微信富文本编辑器的格式。
    """
    if not image_data:
        return content
    
    # 将内容按段落分割
    paragraphs = content.split('\n\n') if '\n\n' in content else content.split('\n')
    
    # 计算插入位置
    total_paragraphs = len(paragraphs)
    if total_paragraphs <= 1:
        # 如果只有一段，在末尾添加图片
        for img_data in image_data:
            image_tag = _create_wechat_image_tag(img_data)
            paragraphs.append(image_tag)
        return '\n\n'.join(paragraphs)
    
    # 平均分布图片
    num_images = min(len(image_data), total_paragraphs)
    interval = total_paragraphs / num_images if num_images > 0 else 1
    
    # 从后往前插入图片
    for i in range(num_images - 1, -1, -1):
        if i < len(image_data):
            position = int(i * interval)
            if position < len(paragraphs):
                img_data = image_data[i]
                image_tag = _create_wechat_image_tag(img_data)
                
                # 在指定位置后插入
                if position + 1 < len(paragraphs):
                    paragraphs.insert(position + 1, image_tag)
                else:
                    paragraphs.append(image_tag)
    
    return '\n\n'.join(paragraphs)


def _create_wechat_image_tag(img_data: dict) -> str:
    """
    创建符合微信富文本编辑器格式的图片标签
    
    基于用户提供的实际微信编辑器图片格式：
    <img class="rich_pages wxw-img" style="width:51px;margin:10px 0;height:27px" contenteditable="false" 
         src="https://mmbiz.qpic.cn/..." 
         data-src="https://mmbiz.qpic.cn/..." 
         data-s="300,640" 
         data-type="png" 
         data-croporisrc="https://mmbiz.qpic.cn/..." 
         data-cropselx2="51" 
         data-cropsely2="27" 
         data-imgfileid="110001857" 
         data-ratio="1" 
         data-w="1024" 
         data-imgqrcoded="1">
    """
    cdn_url = img_data.get("url", "")
    media_id = img_data.get("media_id", "")
    
    # 确定使用的URL
    if cdn_url and cdn_url.startswith("http"):
        # 如果有有效的URL，使用它
        src_url = cdn_url
    else:
        # 否则使用media_id（微信富文本编辑器可以直接使用media_id）
        src_url = media_id
    
    # 生成图片ID
    img_file_id = media_id if media_id else f"img_{hash(src_url) % 1000000}"
    
    # 构建完整的图片标签，匹配微信富文本编辑器的格式
    image_tag = f'''<img class="rich_pages wxw-img" style="width:100%;height:auto;margin:10px 0" contenteditable="false" src="{src_url}" data-src="{src_url}" data-s="300,640" data-type="png" data-croporisrc="{src_url}" data-cropselx2="51" data-cropsely2="27" data-imgfileid="{img_file_id}" data-ratio="1" data-w="1024" data-imgqrcoded="1">'''
    
    return image_tag


def format_wechat_content(content: str) -> str:
    """将Markdown格式转换为微信富文本格式"""
    if not content or not content.strip():
        return content
    
    # 先确保内容编码正确
    if isinstance(content, bytes):
        content = content.decode('utf-8', errors='ignore')
    
    # 清理和标准化内容
    content = content.strip()
    
    # 智能清理HTML标签和属性
    # 先移除常见的HTML属性，但保留标签结构
    content = re.sub(r'\s+style="[^"]*"', '', content)  # 移除style属性
    content = re.sub(r'\s+class="[^"]*"', '', content)  # 移除class属性
    content = re.sub(r'\s+id="[^"]*"', '', content)  # 移除id属性
    
    # 将HTML列表标签转换为Markdown格式
    content = re.sub(r'<li[^>]*>', '\n• ', content)  # <li> 转换为 •
    content = re.sub(r'</li>', '', content)  # 移除 </li>
    content = re.sub(r'<ul[^>]*>', '', content)  # 移除 <ul>
    content = re.sub(r'</ul>', '', content)  # 移除 </ul>
    content = re.sub(r'<ol[^>]*>', '', content)  # 移除 <ol>
    content = re.sub(r'</ol>', '', content)  # 移除 </ol>
    
    # 将段落标签转换为换行
    content = re.sub(r'<p[^>]*>', '\n\n', content)  # <p> 转换为双换行
    content = re.sub(r'</p>', '', content)  # 移除 </p>
    
    # 处理图片标签 - 完全移除
    content = re.sub(r'<img[^>]*>', '', content)  # 移除所有img标签
    
    # 移除其他常见的HTML标签但保留内容
    content = re.sub(r'<div[^>]*>', '', content)  # 移除 <div>
    content = re.sub(r'</div>', '', content)  # 移除 </div>
    content = re.sub(r'<span[^>]*>', '', content)  # 移除 <span>
    content = re.sub(r'</span>', '', content)  # 移除 </span>
    
    # 最后移除任何剩余的HTML标签
    content = re.sub(r'<[^>]+>', '', content)
    
    # 压缩多余空行，但保留段落结构
    content = re.sub(r'\n{3,}', '\n\n', content)
    
    # 标题转换 - 使用更清晰的格式
    content = re.sub(r'^#\s+(.+)$', r'\n\n📜 \1\n\n', content, flags=re.MULTILINE)
    content = re.sub(r'^##\s+(.+)$', r'\n\n🔹 \1\n\n', content, flags=re.MULTILINE) 
    content = re.sub(r'^###\s+(.+)$', r'\n\n▫️ \1\n\n', content, flags=re.MULTILINE)
    
    # 列表项转换 - 改进格式
    content = re.sub(r'^\s*[-*•]\s+', '\n• ', content, flags=re.MULTILINE)
    
    # 强调样式处理 - 使用更突出的标记
    content = re.sub(r'\*\*([^【】]+?)\*\*', r'【\1】', content)  # 加粗，避免与数据标记冲突
    content = re.sub(r'\*([^【】]+?)\*', r'「\1」', content)  # 斜体
    content = re.sub(r'_([^【】]+?)_', r'「\1」', content)  # 下划线
    
    # 链接处理
    content = re.sub(r'\[(.+?)\]\((.+?)\)', r'\1', content)  # 简化链接显示
    
    # 数据标注 - 更清晰的格式
    content = re.sub(r'【【(.+?)】】', r'📊 \1', content)  # 避免嵌套括号
    
    # 处理带冒号的数据格式：【重要数据：具体数据】
    content = re.sub(r'【重要数据：([^】]+)】', r'📊 \1', content)
    content = re.sub(r'【关键信息：([^】]+)】', r'📊 \1', content)
    content = re.sub(r'【统计数据：([^】]+)】', r'📊 \1', content)
    content = re.sub(r'【重要提醒：([^】]+)】', r'⚠️ \1', content)
    
    # 处理不带冒号的格式（保持向后兼容）
    content = re.sub(r'【重要数据】', r'📊 重要数据', content)
    content = re.sub(r'【关键信息】', r'📊 关键信息', content)
    content = re.sub(r'【统计数据】', r'📊 统计数据', content)
    
    # 数字列表处理
    content = re.sub(r'^\s*(\d+)\.\s+', r'\n\1. ', content, flags=re.MULTILINE)
    
    # 引用处理
    content = re.sub(r'^>\s*(.+)$', r'💬 \1', content, flags=re.MULTILINE)
    
    # 确保段落间有清晰分隔
    paragraphs = []
    current_paragraph = ""
    
    for line in content.split('\n'):
        line = line.strip()
        if not line:
            if current_paragraph:
                paragraphs.append(current_paragraph)
                current_paragraph = ""
            continue
        
        # 标题独立成段
        if line.startswith(('📜', '🔹', '▫️')):
            if current_paragraph:
                paragraphs.append(current_paragraph)
                current_paragraph = ""
            paragraphs.append(line)
        # 列表项独立成段
        elif line.startswith(('•', '1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.')):
            if current_paragraph:
                paragraphs.append(current_paragraph)
                current_paragraph = ""
            paragraphs.append(line)
        # 引用独立成段
        elif line.startswith('💬'):
            if current_paragraph:
                paragraphs.append(current_paragraph)
                current_paragraph = ""
            paragraphs.append(line)
        else:
            if current_paragraph:
                current_paragraph += " " + line
            else:
                current_paragraph = line
    
    # 添加最后一段
    if current_paragraph:
        paragraphs.append(current_paragraph)
    
    # 清理空段落并确保格式
    cleaned_paragraphs = []
    for para in paragraphs:
        para = para.strip()
        if para:
            cleaned_paragraphs.append(para)
    
    # 用双换行连接段落，确保清晰分隔
    result = '\n\n'.join(cleaned_paragraphs)
    
    # 最终清理
    result = re.sub(r'\n{3,}', '\n\n', result)
    
    return result.strip()


def format_wechat_publish_content(content: str) -> str:
    """专门用于发布到微信草稿的格式化函数"""
    if not content or not content.strip():
        return content
    
    # 先确保内容编码正确
    if isinstance(content, bytes):
        content = content.decode('utf-8', errors='ignore')
    
    # 将emoji标记转换为微信兼容的HTML格式
    # 标题处理
    content = re.sub(r'📜\s*([^\n]+)', r'<h2>\1</h2>', content)
    content = re.sub(r'🔹\s*([^\n]+)', r'<h3>\1</h3>', content)
    content = re.sub(r'▫️\s*([^\n]+)', r'<h4>\1</h4>', content)
    
    # 强调文本处理
    content = re.sub(r'【([^】]+)】', r'<strong>\1</strong>', content)
    content = re.sub(r'「([^」]+)」', r'<em>\1</em>', content)
    
    # 数据标记处理
    content = re.sub(r'📊\s*([^\n]+)', r'<strong>📊 \1</strong>', content)
    
    # 列表处理 - 将连续的列表项包装在ul标签中
    lines = content.split('\n')
    result_lines = []
    in_list = False
    
    for line in lines:
        line = line.strip()
        if line.startswith('• '):
            if not in_list:
                result_lines.append('<ul>')
                in_list = True
            # 移除项目符号，添加li标签
            item_content = line[2:].strip()
            result_lines.append(f'<li>{item_content}</li>')
        else:
            if in_list:
                result_lines.append('</ul>')
                in_list = False
            if line:  # 非空行
                result_lines.append(line)
    
    # 关闭未关闭的列表
    if in_list:
        result_lines.append('</ul>')
    
    # 将非标签行包装在p标签中
    final_lines = []
    for line in result_lines:
        line = line.strip()
        if not line:
            continue
        
        # 如果不是 HTML 标签开头，包装在 p 标签中
        if not line.startswith(('<h', '<ul', '</ul', '<li', '<strong', '<em')):
            final_lines.append(f'<p>{line}</p>')
        else:
            final_lines.append(line)
    
    # 返回格式化结果
    return '\n'.join(final_lines)


def extract_keywords_from_text(text: str, max_keywords: int = 5) -> List[str]:
    """从文本中提取关键词（简单实现）"""
    # 移除标点符号和特殊字符
    cleaned_text = re.sub(r'[^\w\s]', '', text)
    
    # 分词（简单按空格分割）
    words = cleaned_text.split()
    
    # 过滤短词和常用词
    stop_words = {'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'}
    
    keywords = []
    for word in words:
        if len(word) > 1 and word not in stop_words:
            keywords.append(word)
    
    # 简单去重并限制数量
    unique_keywords = list(dict.fromkeys(keywords))
    return unique_keywords[:max_keywords]


def validate_theme_data(theme_data: Dict[str, Any]) -> Dict[str, str]:
    """验证主题数据"""
    errors = {}
    
    # 验证必填字段
    required_fields = ['name', 'description']
    for field in required_fields:
        if not theme_data.get(field):
            errors[field] = f"{field}不能为空"
    
    # 验证名称长度
    if theme_data.get('name') and len(theme_data['name']) > 255:
        errors['name'] = "主题名称不能超过255个字符"
    
    # 验证内容长度
    if theme_data.get('content_length'):
        try:
            length = int(theme_data['content_length'])
            if length < 100:
                errors['content_length'] = "内容长度不能少于100字符"
            elif length > 10000:
                errors['content_length'] = "内容长度不能超过10000字符"
        except ValueError:
            errors['content_length'] = "内容长度必须是数字"
    
    return errors


def validate_article_data(article_data: Dict[str, Any]) -> Dict[str, str]:
    """验证文章数据"""
    errors = {}
    
    # 验证标题
    title = article_data.get('title', '')
    if not title:
        errors['title'] = "标题不能为空"
    elif len(title) > 200:
        errors['title'] = "标题不能超过200个字符"
    
    # 验证内容
    content = article_data.get('content', '')
    if not content:
        errors['content'] = "内容不能为空"
    elif len(content) < 100:
        errors['content'] = "内容长度不能少于100字符"
    
    # 验证摘要
    summary = article_data.get('summary', '')
    if summary and len(summary) > 500:
        errors['summary'] = "摘要不能超过500个字符"
    
    return errors


def safe_get(data: Dict, key: str, default: Any = None) -> Any:
    """安全获取字典值"""
    try:
        return data.get(key, default)
    except (AttributeError, KeyError):
        return default


def format_datetime(dt: datetime) -> str:
    """格式化日期时间"""
    if dt is None:
        return ""
    return dt.strftime('%Y-%m-%d %H:%M:%S')


def parse_datetime(datetime_str: str) -> Optional[datetime]:
    """解析日期时间字符串"""
    if not datetime_str:
        return None
    
    try:
        return datetime.fromisoformat(datetime_str.replace('Z', '+00:00'))
    except ValueError:
        logger.warning(f"无法解析日期时间: {datetime_str}")
        return None